<template>
  <el-container direction="horizontal" :style="{ height: viewHeight + 'px' }">
    <el-aside
      width="175px"
      v-show="asideLeftShow"
      style="overflow: scroll"
      :style="{ paddingBottom: asidePaddingBottom }"
    >
      <el-row type="flex" align="middle">
        <el-col :span="18">
          <el-input
            v-model.trim="searchValue"
            prefix-icon="el-icon-search"
            style="width: 100%"
            clearable
          >
          </el-input>
        </el-col>
        <el-col :span="3">
          <div style="text-align: center">
            <svg-icon
              slot="suffix"
              @click="expandComponent"
              icon-class="vertical-bottom"
              style="font-size: 14px; color: #999999"
            ></svg-icon>
          </div>
        </el-col>
        <el-col :span="3">
          <div style="text-align: center">
            <svg-icon
              slot="suffix"
              @click="collapseComponent"
              icon-class="vertical"
              style="font-size: 14px; color: #999999"
            ></svg-icon>
          </div>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="24">
          <el-collapse v-model="activeNames">
            <el-collapse-item
              :title="components.title"
              v-for="components in searchelements"
              :key="components['title']"
              class="itemColor"
              :name="components.name"
            >
              <ul class="element_ul">
                <li
                  v-for="(subelement, idx) in components.toolGroupName"
                  :key="idx"
                  ref="subItem"
                >
                  <div class="divElement">
                    <img
                      v-bind="subelement"
                      class="element-img"
                      :src="`${subelement.icon}`"
                    />

                    <div class="element-title">{{ subelement.title }}</div>
                  </div>
                </li>
              </ul>
            </el-collapse-item>
          </el-collapse>
        </el-col>
      </el-row>
    </el-aside>
    <div class="mLeft">
      <div class="bl_move" :style="{ height: viewHeight + 'px' }">
        <svg-icon
          icon-class="open"
          class="bl_fold"
          @click="handleToggleDrawer"
        ></svg-icon>
        <!-- <a href="javascript:void(0)" title="展开" class="bl_fold" @click="handleToggleDrawer">
          <i class="fa fa-caret-up" aria-hidden="true"></i>
        </a> -->
      </div>
      <!-- <svg-icon icon-class="open" class="bl_fold"></svg-icon> -->
    </div>
    <el-main style="padding: 10px" :style="{ height: viewHeight + 'px' }">
      <div class="grid-content_main">
        <div class="tool-bar">
          <!--<input ref="importInput" class="hide" type="file" @change="">-->
          <img
            src="./icon/views.png"
            style="width: 20px; height: 20px; margin-right: 10px"
            title="切换视图"
            @click="switchToView"
          />
          <img
            src="./icon/navigation.png"
            style="width: 20px; height: 20px; margin-right: 10px"
            title="打开/关闭导航器"
            @click="switchNavigate"
          />
          <img
            src="./icon/plus.png"
            style="width: 20px; height: 20px; margin-right: 10px"
            title="放大"
            @click="zoomBig"
          />
          <img
            src="./icon/reduce.png"
            style="width: 20px; height: 20px; margin-right: 10px"
            title="缩小"
            @click="zoomSmall"
          />
          <img
            src="./icon/reset.png"
            style="width: 20px; height: 20px; margin-right: 10px"
            title="重置缩放"
            @click="resetActualSize"
          />
          <img
            src="./icon/setting.png"
            style="width: 20px; height: 20px; margin-right: 10px"
            title="设置"
            @click="appConfig"
          />
        </div>
        <div
          id="graphContainer"
          class="graphMain"
          ref="graphContainer"
          style="
            position: relative;
            overflow: hidden;
            cursor: pointer;
            width: 100%;
          "
          :style="{ height: viewHeight + 'px' }"
        ></div>
        <div id="graphNavigation" class="outline-wrapper" v-show="showNav">
          <h4>导航器</h4>
          <div id="graphOutline" ref="graphOutline" />
        </div>
      </div>
    </el-main>
    <CodeDialog
      @codeSubmit="codeSubmit"
      ref="codeRef"
      :codeText="codeText"
      :dialogVisible.sync="codeDialogVisible"
    ></CodeDialog>
  </el-container>
</template>

<script>
const noConnect = ["functionList"];
const delay = (function () {
  let timer = 0;
  return function (callback, ms) {
    clearTimeout(timer);
    timer = setTimeout(callback, ms);
  };
})();
import FileSaver from "file-saver";
import mxgraph from "@/components/mxgraph/index";
import { base64EncodeUnicode } from "@/utils/utils";
import { componentsData } from "@/components/mxgraph/common/data";
import { base64DecodeUnicode } from "@/utils/utils";
import { constants } from "./common/constants";
import not from "ramda/src/not";
import { generateId } from "@/utils/index";
import { mapGetters } from "vuex";
import { streamKey } from "@/utils/local";
import CodeDialog from "./CodeDialog/index.vue";
import { edgeReadFile } from "@/api/siddhi";
const {
  mxOutline,
  mxEditor,
  mxToolbar,
  mxGraphModel,
  mxGraph,
  mxCell,
  mxGeometry,
  mxEvent,
  mxUtils,
  mxCodec,
  mxUndoManager,
  mxKeyHandler,
  mxClipboard,
  mxImage,
  mxCellTracker,
  mxStencil,
  mxStencilRegistry,
  mxConstants,
  mxHierarchicalLayout,
  mxEdgeHandler,
  mxGraphView,
  mxFastOrganicLayout, //组织状布局
  mxCompactTreeLayout, //树状布局
  mxShape,
  mxMultiplicity,
  mxConnectionHandler,
  mxEventObject,
  mxVertexHandler,
  mxConstraintHandler,
  mxResources,
  mxRubberband,
} = mxgraph;

export default {
  name: "designView",
  components: {
    CodeDialog,
  },
  props: {
    save: {},
    viewHeight: {
      type: String,
      default: "",
    },
    viewWidth: {
      type: String,
      default: "",
    },
    objectJson: {
      type: String,
      default: "",
    },
    objectMxl: {
      type: String,
      default: "",
    },
    objectState: {
      type: String,
      default: "",
    },
    appData: {
      type: Object,
      default: () => {},
    },
    mxTitle: {
      type: String,
      default: "",
    },
    codeText: {
      type: String,
      default: "",
    },
    isBottom: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      codeDialogVisible: false,
      show: true,
      selectEdge: {},
      selectVertex: {},
      // clientHeight: document.body.clientHeight,
      // clientWidth: document.body.clientWidth,
      showGraph: true,
      showGraphLWidth: 3,
      showGraphRWidth: 20,
      activeNames: [],
      searchValue: "",
      searchelements: [],
      asideLeftShow: true,
      editor: null,
      graphOjbect: null,
      outline: null,
      showNav: true,
      showRight: { title: "设置", open: true, nodeType: "0" },
      selectCell: null,
      ObjectData: {},
      mxGraphXml: "",
      // mxCellId: generateId(), //替换之前的手动 ++ (随机id)
      mxCellId: 0, //替换之前的手动 ++ (随机id)
      targetCell: {},
      sourceCell: {},
      domArray: [],
      highlight: [],
    };
  },
  computed: {
    ...mapGetters(["ediEdgeTabs", "activeTab"]),
    componentsData: () => componentsData,
    asidePaddingBottom() {
      // 打开控制台-左侧菜单增加内边距防止下边挡住
      const consoleOpen = this.$store.state.siddhi.consoleOpen;
      return consoleOpen ? "220px" : "0";
    },
  },
  watch: {
    searchValue() {
      delay(() => {
        this.doSearch();
      }, 500);
    },
    viewHeight: {
      handler: function (newData, oldData) {
        // console.info("layout子  prop watch  传递  变化高度：" + newData);
      },
      immediate: true,
    },

    viewWidth: {
      handler: function (newData, oldData) {
        // console.info(" layout子 prop watch 传递  变化宽度：" + newData);
      },
      immediate: true,
    },
    objectJson: {
      handler: function (newData, oldData) {
        if ("" !== newData) {
          let tempData = base64DecodeUnicode(newData);
          this.ObjectData = JSON.parse(tempData);

          // console.info(this.ObjectData.siddhiAppConfig);
          // console.info("  graph  watch objectJson :完毕");
        }
      },
      immediate: true,
      deep: true,
    },
    objectMxl: {
      handler: function (newData, oldData) {
        if ("" !== newData) {
          this.mxGraphXml = newData;
        }
      },
      immediate: true,
    },
    activeTab: {
      handler: function (newData, oldData) {
        const { configTiltle } = constants;
        const { appData } = newData;
        const appDataKey = configTiltle.map((item) => item.type);
        appDataKey.forEach((item) => {
          if (item.indexOf(".") == -1) {
            appData[item].forEach((ele) => {
              this.$nextTick(() => {
                this.sethighlight(ele.id, ele.isDel);
              });
            });
          } else {
            const typeItem = item.split(".");
            appData[typeItem[0]][typeItem[1]].forEach((ele) => {
              this.$nextTick(() => {
                this.sethighlight(ele.id, ele.isDel);
              });
            });
          }
        });
      },
      deep: true,
      immediate: true,
    },
    mxTitle(newTitle, oldTitle) {
      this.setGraphTitle(newTitle);
    },
    // mxTitle: {
    //   handler: function (newTitle, oldTitle) {
    //     this.setGraphTitle(newTitle);
    //   },
    //   immediate: true,
    // },
  },
  mounted() {
    //console.info(JSON.stringify(this.appData))
    //let xx= this.mxGraphXml;
    this.searchelements = this.componentsData;
    this.createGraph(); //创建布局容器
    this.initGraph(); //初始化
    this.$nextTick(() => {
      this.initToolbar();
    });
    this._listenEvent(); //监听事件

    this.initKeyHandler(); // 初始化键盘事件
    this.initDataLayout();
    this.initContentMenu(); // 初始化上下文菜单
  },
  beforeDestroy() {},

  methods: {
    codeSubmit(siddhiName) {
      this.$emit("codeSubmit", siddhiName);
    },
    // 连线校验
    connectionVas() {
      this.graphOjbect.multiplicities = [];
      const { configTiltle } = constants;
      configTiltle.forEach((ele) => {
        const titles = ele.Source.map((item) => item.title).join(",");
        const tes1 = `${ele.title}只能连接${ele.min}个${titles}节点`;
        const tes2 = `${ele.title}只能连接${titles}节点`;
        this.graphOjbect.multiplicities.push(
          new mxMultiplicity(
            false,
            ele.type,
            null,
            null,
            ele.min,
            ele.max,
            ele.Source.map((item) => item.type),
            tes1,
            tes2
          )
        );
      });

      // new mxRubberband(this.graphOjbect);
      // mxUtils.confirm(mxResources.get("saveSuccess"));
    },
    //移除选中状态
    removeSelectionCells() {
      if (!this.graphOjbect) return;
      this.graphOjbect.getModel().beginUpdate();
      try {
        var _cell = this.graphOjbect.getSelectionCells();
        this.graphOjbect.removeSelectionCells(_cell);
      } finally {
        this.graphOjbect.refresh();
        this.graphOjbect.getModel().endUpdate();
      }
    },
    //设置标题
    setGraphTitle(title) {
      if (!title) return;
      if (!this.graphOjbect) return;
      this.graphOjbect.getModel().beginUpdate();
      var _cell = this.graphOjbect.getSelectionCells();
      try {
        if (!_cell || _cell.length == 0) return;
        _cell[0].title = title;
      } finally {
        this.graphOjbect.refresh();
        this.graphOjbect.getModel().endUpdate();
        //修改完标题之后 移除选中状态(有个bug会执行两次,然后会把上一次的title修改掉:原因是上次选中的状态没有取消)
        this.removeSelectionCells();
      }
    },
    createGraph() {
      this.editor = new mxEditor();
      this.graphOjbect = this.editor.graph;
      this.editor.setGraphContainer(this.$refs.graphContainer);
      // let model = new mxGraphModel();
      // this.graphOjbect = new mxGraph(this.$refs.graphContainer, model);
      this.outline = new mxOutline(this.graphOjbect, this.$refs.graphOutline);
    },
    initGraph() {
      let that = this;
      if (this.R.isNil(this.graphOjbect)) {
        return;
      }
      this.graphOjbect.setConnectable(true); // 允许连线
      this.graphOjbect.fit(); //自适应
      this.graphOjbect.center(true, true, 0.1, 0.1); //将画布放到容器适当位置
      var sc = this.graphOjbect.getView().getScale(); //获取当前的缩放比例
      this.graphOjbect.zoomTo(Math.round(sc)); //在缩放一半，否则是满屏状态，不好看

      var sc = this.graphOjbect.getView().getScale(); //获取当前的缩放比例
      this.graphOjbect.setCellsEditable(false); // 不可修改
      //this.graphOjbect.setEnabled(false);//对图形进行拖拽拉伸(节点、边)等操作
      this.graphOjbect.setCellsMovable(true); //允许拖拽流程图
      this.graphOjbect.setAutoSizeCells(true);
      this.graphOjbect.setMultigraph(false);
      this.graphOjbect.setSplitEnabled(false);
      // this.graphOjbect.setCellsLocked(true);//设置元素可编辑,不然无法自动布局;设置false元素可移动
      this.graphOjbect.setCellsResizable(false); // 禁止改变元素大小
      this.graphOjbect.setCellsSelectable(true); //设置cell可选中
      this.graphOjbect.setPanning(true); //设置面板可以扩大
      this.graphOjbect.centerZoom = true; //是否已图形的中心进行放大，否则以元素为中心放大
      this.graphOjbect.setAllowLoops(true); // 允许连线的目标和源是同一元素
      this.graphOjbect.convertValueToString = (cell) => {
        // 从value中获取显示的内容
        return this.R.prop("title", cell);
      };
      mxEvent.disableContextMenu(this.$refs.graphContainer);
      mxEdgeHandler.prototype.snapToTerminals = true;
      this.graphOjbect.setAllowDanglingEdges(false);
      this.graphOjbect.setDisconnectOnMove(false);
      this.graphOjbect.setCloneInvalidEdges(false);

      this.graphOjbect.setAllowNegativeCoordinates(false);
      var style = this.graphOjbect.getStylesheet().getDefaultEdgeStyle();
      style[mxConstants.STYLE_STROKECOLOR] = constants.VERTEX_SELECTION_COLOR;
      style[mxConstants.STYLE_STROKEWIDTH] = 2;
      style[mxConstants.EDGE_SELECTION_STROKEWIDTH] = 5;
      style[mxConstants.LABEL_HANDLE_SIZE] = 5;
      style[mxConstants.ARROW_SIZE] = 11;
      style[mxConstants.ARROW_WIDTH] = 11;
      style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_OVAL;
      style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_OPEN;
      style[mxConstants.STYLE_ROUNDED] = true; //圆角连线
      style[mxConstants.STYLE_EDGE] = mxEdgeStyle.OrthConnector; //这里控制箭头方向 ElbowConnector

      mxGraph.prototype.getAllConnectionConstraints = (terminal) => {
        if (terminal != null && terminal.shape != null) {
          if (terminal.shape.stencil != null) {
            if (terminal.shape.stencil != null) {
              return terminal.shape.stencil.constraints;
            }
          } else if (terminal.shape.constraints != null) {
            if (!terminal.cell.edge) {
              return terminal.shape.constraints;
            } else {
              return null;
            }
          }
        }

        return null;
      };
      // 重写alert弹框
      mxUtils.alert = (msg) => {
        return this.$msg(msg);
      };
      mxShape.prototype.constraints = [
        new mxConnectionConstraint(new mxPoint(0.5, 0), true),
        new mxConnectionConstraint(new mxPoint(0, 0.5), true),
        new mxConnectionConstraint(new mxPoint(1, 0.5), true),
        new mxConnectionConstraint(new mxPoint(0.5, 1), true),
      ];

      this.graphOjbect.connectionHandler.isConnectableCell = function (cell) {
        if (that.graphOjbect.getModel().isEdge(cell)) {
          return true;
        } else {
          var geo =
            cell != null ? that.graphOjbect.getCellGeometry(cell) : null;

          return geo != null ? geo.relative : false;
        }
      };
      var connectionHandlerCreateShape =
        mxConnectionHandler.prototype.createShape;
      mxConnectionHandler.prototype.createShape = function () {
        var shape = connectionHandlerCreateShape.apply(this, arguments);
        shape.isDashed = false;
        return shape;
      };

      mxVertexHandler.prototype.isSelectionDashed = function () {
        return false;
      };
      mxVertexHandler.prototype.getSelectionColor = function () {
        return constants.VERTEX_SELECTION_COLOR;
      };
      mxEdgeHandler.prototype.getSelectionColor = function () {
        return constants.VERTEX_SELECTION_COLOR;
      };
      mxConstraintHandler.prototype.createHighlightShape = function () {
        var hl = new mxEllipse(
          null,
          constants.POINT_FILL_COLOR,
          constants.VERTEX_SELECTION_COLOR,
          -1
        );
        hl.opacity = 100;

        return hl;
      };

      mxConnectionHandler.prototype.getEdgeColor = function (valid) {
        return valid
          ? constants.VERTEX_SELECTION_COLOR
          : constants.VERTEX_SELECTION_COLOR;
      };
      this.connectionVas();
    },
    initDataLayout() {
      if (this.objectMxl != "" && this.objectMxl != undefined) {
        var jsonObj = this.$x2js.xml2js(this.objectMxl); //res (xml数据)
        if (jsonObj.mxGraphModel.root != "undefined") {
          var mxCellArray = jsonObj.mxGraphModel.root.mxCell;
          mxCellArray.forEach((item, domIndex) => {
            // mxGeometry
            if (item["_vertex"] != undefined && item["_type"] != undefined) {
              this.$set(item, "_value", item["_type"]);
              item[
                "_style"
              ] = `fillColor=#E9E9E9;strokeColor=#E4E4E4;strokeWidth=2;shape=label;align=left;spacingLeft=34;verticalAlign=middle;imageAlign=left;imageVerticalAlign=center;image=./mxgraph/images/${item["_type"]}.svg`;
              if (item["_type"] == "partitionList") {
                item["_style"] =
                  "shape=swimlane;startSize=0;noLabel=no;hotspotSize=300";
                item.mxGeometry._width = "250";
                item.mxGeometry._height = "250";
              }
            }
          });
        }
        let resultXML = this.$x2js.js2xml(jsonObj);
        this.importModelXML(resultXML, mxCellArray);
      }
    },
    addCell(toolItem, x, y) {
      const noResizable = ["partitionList"];
      // 禁止连接线
      let { width, height } = toolItem;
      const styleObj = toolItem["style"];
      let style = Object.keys(styleObj)
        .map((attr) => `${attr}=${styleObj[attr]}`)
        .join(";");
      const parent = this.graphOjbect.getDefaultParent();
      var xmlDocument = mxUtils.createXmlDocument();
      let nodeType = toolItem.type;
      var CellNode = xmlDocument.createElement(nodeType);
      if (nodeType == "partitionList") {
        // style = "shape=swimlane;startSize=20;";
        // width = "250";
        // height = "250";
        //
        // this.graphOjbect.cellEditor.graph.cellsResizable = true;
      } else {
        // this.graphOjbect.setCellsResizable(false);
      }
      this.graphOjbect.getModel().beginUpdate();
      try {
        let vertex = this.graphOjbect.insertVertex(
          parent,
          this.mxCellId++,
          // generateId(),
          CellNode,
          x + 10,
          y,
          width,
          height,
          style
        );
        // 设置部分节点不可连线
        vertex.setConnectable(!noConnect.includes(nodeType));
        // 设置分区节点可以缩放
        const SelectionCell = this.graphOjbect.getSelectionCell();
        // vertex.cellsResizable = true;
        Object.assign(vertex, { type: toolItem.type, title: toolItem.title }); //节点类型
      } finally {
        this.graphOjbect.getModel().endUpdate();
        this.$store.commit("siddhi/SET_IS_SAVE", true);
      }
    },
    initToolbar() {
      let that = this;
      that.domArray = this.$refs.subItem;
      if (!(that.domArray instanceof Array) || that.domArray.length <= 0) {
        return;
      }
      this.componentsData.forEach((toolItem, domIndex) => {
        let { width, height } = toolItem;
        // width = 250;
        // height = 250;
        let subComponent = toolItem["toolGroupName"];
        subComponent.forEach((dom, domIndex) => {
          that.domArray.forEach((group, domIndex) => {
            let tempCom = group.innerText;
            if (dom["title"] == tempCom) {
              let imgStyle = dom["style"];
              let dropHandler = (graph, evt, cell, x, y) => {
                // 节流函数-解决拖拽节点会触发多个问题
                delay(() => {
                  this.addCell(dom, x, y);
                }, 1);
              };
              let createDragPreview = () => {
                // const elt = document.createElement("div");
                //
                // elt.style.width = `${width}px`;
                // elt.style.height = `${height}px`;
                // elt.style.background= 'rgba(233, 233, 233, 0.41)';
                //
                // elt.style['background-image'] = "url("+imgStyle.image+")";
                // elt.style['background-repeat'] = "no-repeat";
                //
                // elt.innerHTML="<span style='font-size: 8px;margin-left: 32px;text-align: center;color: #8B5742'>"+tempCom+"</span>";
                // elt.style.textAlign="center"
                function createDiv() {
                  let elem = document.createElement("div");
                }
                var elt = createDiv();
                return elt;
              };
              mxUtils.makeDraggable(
                group,
                this.graphOjbect,
                dropHandler,
                createDragPreview(),
                -41,
                -41,
                false,
                true
              );
            }
          });
        });
      });
    },
    handleToggleDrawer() {
      this.asideLeftShow = !this.asideLeftShow;
    },
    doSearch(val) {
      let searchValue = this.searchValue;
      let totalPerson = this.componentsData;
      this.searchelements = [];
      let testPerson = [];
      this.activeNames = [];
      totalPerson.map((comp) => {
        let cId = comp.id;
        let inner = comp.toolGroupName;
        let isSearch = false;
        let userArr = [];
        inner.map((ele) => {
          if (ele.title.includes(searchValue)) {
            userArr.push(ele);
            isSearch = true;
          }
        });
        if (isSearch) {
          let newObj = {};
          if (cId === "streamsGroup") {
            newObj = {
              id: cId,
              title: "流程构件",
              toolGroupName: userArr,
              name: "streamsGroup",
              icon: "/editor/images/streams.svg",
            };
          } else if (cId === "inOutGroup") {
            newObj = {
              id: false,
              title: "输入/输出",
              toolGroupName: userArr,
              name: "inOutGroup",
              icon: "/editor/images/streams.svg",
            };
          } else if (cId === "collectionsGroup") {
            newObj = {
              id: cId,
              title: "收集器",
              toolGroupName: userArr,
              name: "collectionsGroup",
              icon: "/editor/images/streams.svg",
            };
          } else if (cId === "queryGroup") {
            newObj = {
              id: cId,
              title: "查询",
              toolGroupName: userArr,
              name: "queryGroup",
              icon: "/editor/images/streams.svg",
            };
          } else if (cId === "functionGroup") {
            newObj = {
              id: cId,
              title: "函数",
              toolGroupName: userArr,
              name: "functionGroup",
              icon: "/editor/images/streams.svg",
            };
          }
          testPerson.push(newObj);
          this.activeNames.push(newObj.name);
          if (searchValue.length > 0) {
            // 包含有搜索的字段的时候，把每个值的key给value1
          } else {
            this.value1 = [];
          }
        }
      });

      this.searchelements = testPerson;

      this.$nextTick(() => {
        this.initToolbar();
      });
    },
    _listenEvent() {
      let that = this;
      // 监听 mxEvent.CHANGE 事件
      //const mxGraphSelectionModel = this.graph.getSelectionModel()
      //mxGraphSelectionModel.addListener(mxEvent.CHANGE, this.handleSelectionChange)
      // 监听 mxEvent.DOUBLE_CLICK 事件
      this.graphOjbect.addListener(mxEvent.DOUBLE_CLICK, (graph, evt) => {
        // 监听双击事件
        const cells = this.R.pathOr([], ["properties", "cell"], evt);
        //query节点 编辑前提示 让添加一个前置节点input element
        let cell;
        if (cells instanceof Array) {
          if (cells.length != 0) {
            cell = cells[0];
          }
        } else {
          if (cells.type != undefined) {
            cell = cells;
          }
        }
        // console.info("当前节点：" + cell.id); //这里莫名报错 注释了
        that.openDrawer(cell);
      });

      this.graphOjbect.connectionHandler.addListener(
        mxEvent.CONNECT,
        (sender, evt) => {
          // that.graphOjbect.multiplicities.push(
          //   new mxMultiplicity(true, null, null, null, 0, 0, null, "阻止连线")
          // );
          // this.connectionVas();
          var cells = [evt.getProperty("cell")];
          if (cells[0].source.connectable && cells[0].target.connectable) {
            console.log("链接=======>>>>>");
            this.$store.commit("siddhi/SET_IS_SAVE", true);
            // let targetCell = cells[0].target;
            // let sourceCell = cells[0].source;
            // let sourceId = sourceCell.id;
            // let targetId = targetCell.id;
            // const sType = sourceCell.type;
            // const tType = targetCell.type;
            // const tValue = targetCell.value;

            // this.graphOjbect.readGraphModel(tValue);
          }
        }
      );

      this.graphOjbect.addMouseListener({
        currentState: null,
        previousStyle: null,
        mouseDown: function (sender, me) {
          if (this.currentState != null) {
            this.dragLeave(me.getEvent(), this.currentState);
            this.currentState = null;
          }
        },
        mouseMove: function (sender, me) {
          if (this.currentState != null && me.getState() == this.currentState) {
            return;
          }

          var tmp = that.graphOjbect.view.getState(me.getCell());

          // Ignores everything but vertices
          if (
            that.graphOjbect.isMouseDown ||
            (tmp != null && !that.graphOjbect.getModel().isVertex(tmp.cell))
          ) {
            tmp = null;
          }

          if (tmp != this.currentState) {
            if (this.currentState != null) {
              this.dragLeave(me.getEvent(), this.currentState);
            }

            this.currentState = tmp;

            if (this.currentState != null) {
              this.dragEnter(me.getEvent(), this.currentState);
            }
          }
        },
        mouseUp: function (sender, me) {},
        dragEnter: function (evt, state) {
          if (state != null) {
            this.previousStyle = state.style;
            state.style = mxUtils.clone(state.style);
            updateStyle(state, true);
            state.shape.apply(state);
            state.shape.reconfigure();
          }
        },
        dragLeave: function (evt, state) {
          if (state != null) {
            state.style = this.previousStyle;
            updateStyle(state, false);
            if (state.shape != null) {
              state.shape.apply(state);
              state.shape.reconfigure();
            }
          }
        },
      });
      function updateStyle(state, hover) {
        if (hover) {
          //state.style[mxConstants.STYLE_FILLCOLOR] = 'transparent';
        }

        // Sets rounded style for both cases since the rounded style
        // is not set in the default style and is therefore inherited
        // once it is set, whereas the above overrides the default value
        state.style[mxConstants.STYLE_ROUNDED] = hover ? "0" : "1";
        state.style[mxConstants.STYLE_STROKEWIDTH] = hover ? "1" : "1";
        state.style[mxConstants.STYLE_FONTSTYLE] = hover
          ? mxConstants.FONT_BOLD
          : "0";
        state.style[mxConstants.STYLE_STROKECOLOR] = hover
          ? constants.VERTEX_SELECTION_COLOR
          : constants.VERTEX_SELECTION_LIGHT_COLOR;
      }
      this.graphOjbect.addListener(mxEvent.CLICK, function (sender, evt) {
        var cell = evt.getProperty("cell");
        var model = that.graphOjbect.getModel();
        model.beginUpdate();
        try {
          that.graphOjbect.setCellStyles("strokewidth", "2", [cell]);
        } finally {
          model.endUpdate();
        }
      });
    },
    openDrawer(cell) {
      let fontNode = {};
      let AfterNode = {};

      if (cell != null && cell != undefined && cell.type != undefined) {
        fontNode = this.getFrontNodeRelate(cell);
        AfterNode = this.getAfterNodeRelate(cell);
        if (cell.type.includes("streamList")) {
          this.showNode(cell, fontNode, AfterNode);
        } else if (cell.type.includes("triggerList")) {
          this.showNode(cell, fontNode, AfterNode);
        } else if (cell.type.includes("queryLists")) {
          if (this.validNodeExitsEdges(cell)) {
            //需要获取前一个节点的属性，譬如stream属性
            if (this.validNodeExitsFrontEdges(cell)) {
              fontNode = this.getFrontNodeRelate(cell);
            } else {
              this.$msg({
                type: "warning",
                message: "请连接一个输入节点!",
              });
              return;
            }
            if (this.validNodeExitsAfterEdges(cell)) {
              //需要获取后一个节点的属性，譬如stream属性
              AfterNode = this.getAfterNodeRelate(cell);
            } else {
              this.$msg({
                type: "warning",
                message: "请连接一个输出节点!",
              });
              return;
            }
            this.showNode(cell, fontNode, AfterNode);
          } else {
            this.$msg({ type: "warning", message: "请连接一个输入节点!" });
            return;
          }
        } else if (cell.type.includes("sinkList")) {
          if (this.validNodeExitsEdges(cell)) {
            //需要获取前一个节点的属性，譬如stream属性
            if (this.validNodeExitsFrontEdges(cell)) {
              fontNode = this.getFrontNodeRelate(cell);
            }
            this.showNode(cell, fontNode, AfterNode);
          } else {
            this.$msg({ type: "warning", message: "请连接一个输入节点!" });
            return;
          }
        } else if (cell.type.includes("sourceList")) {
          if (this.validNodeExitsEdges(cell)) {
            AfterNode = this.getAfterNodeRelate(cell);
            this.showNode(cell, fontNode, AfterNode);
          } else {
            this.$msg({ type: "warning", message: "请连接一个流节点!" });
            return;
          }
        } else if (cell.type.includes("functionList")) {
          this.showNode(cell, null, null);
        } else if (cell.type.includes("windowList")) {
          this.showNode(cell, fontNode, AfterNode);
        } else if (cell.type.includes("tableList")) {
          this.showNode(cell, fontNode, AfterNode);
        } else if (cell.type.includes("partitionList")) {
          this.showNode(cell, fontNode, AfterNode);
        } else if (cell.type.includes("aggregationList")) {
          if (this.validNodeExitsEdges(cell)) {
            //需要获取前一个节点的属性，譬如stream属性
            if (this.validNodeExitsFrontEdges(cell)) {
              fontNode = this.getFrontNodeRelate(cell);
            }
            this.showNode(cell, fontNode, AfterNode);
          } else {
            this.$msg({ type: "warning", message: "请连接一个输入节点!" });
            return;
          }
          // this.showNode(cell, null, null);
        }
      }
    },
    getRelateCell(cell, relate) {
      let cellData = _.cloneDeep(
        this.$store.getters["siddhi/getCell"]({
          id: cell.id,
          type: cell.type,
        })
      );
      return {
        ...cellData,
        type: cell.type,
      };
    },
    validNodeExitsEdges(cell) {
      let flag = false;
      // 查看是否连线
      if (cell && cell.isVertex) {
        var edges = cell.edges;
        if (edges != null && edges.length > 0) {
          flag = true;
        }
      }
      return flag;
    },
    validNodeExitsFrontEdges(cell) {
      let flag = false; //当前节点是否连接前一个节点
      if (cell && cell.isVertex) {
        var edges = cell.edges;
        var edge;
        if (edges != null) {
          for (var i = 0; i < edges.length; i++) {
            edge = edges[i];
            if (cell.id == edge.target.id) {
              flag = true;
            }
          }
        }
      }
      return flag;
    },
    validNodeExitsAfterEdges(cell) {
      let flag = false; //当前节点是否连接后一个节点
      if (cell && cell.isVertex) {
        var edges = cell.edges;
        var edge;
        if (edges != null) {
          for (var i = 0; i < edges.length; i++) {
            edge = edges[i];
            if (cell.id == edge.source.id) {
              flag = true;
            }
          }
        }
      }
      return flag;
    },
    getFrontNodeRelate(cell) {
      // 如果上节点是两个或者多个的情况,返回全部的
      let frontNode = [];
      if (cell && cell.isVertex) {
        var edges = cell.edges;
        var edge;
        if (edges != null) {
          for (var i = 0; i < edges.length; i++) {
            edge = edges[i];
            if (cell.id == edge.target.id) {
              frontNode.push(this.getRelateCell(edge.source, "target")); //获取前一个节点
            }
          }
        }
      }
      return frontNode.length <= 1 ? frontNode[0] : frontNode;
    },
    getAfterNodeRelate(cell) {
      // 如果节点是两个或者多个的情况,返回全部的
      let afterNode = [];
      if (cell && cell.isVertex) {
        var edges = cell.edges;
        var edge;
        if (edges != null) {
          for (var i = 0; i < edges.length; i++) {
            edge = edges[i];
            if (cell.id == edge.source.id) {
              afterNode.push(this.getRelateCell(edge.target, "source")); //获取后一个节点
            }
          }
        }
      }
      return afterNode.length <= 1 ? afterNode[0] : afterNode;
    },
    async switchToView() {
      // this.save()
      await this.save();
      let path = "workspace/" + this.$store.getters.activeTab.name + ".siddhi";
      edgeReadFile(path).then((res) => {
        this.codeDialogVisible = true;
        this.$nextTick(() => {
          this.$refs.codeRef.aceSetValue(res.data.content);
        });
      });

      // var encoder = new mxCodec();
      // var node = encoder.encode(this.graphOjbect.getModel());
      // mxUtils.popup(mxUtils.getPrettyXml(node), true);
    },
    switchNavigate() {
      this.showNav = !this.showNav;
    },
    zoomSmall() {
      this.graphOjbect.zoomOut();
    },
    zoomBig() {
      this.graphOjbect.zoomIn();
    },
    resetActualSize() {
      this.graphOjbect.zoomActual();
    },
    initContentMenu() {
      this.graphOjbect.popupMenuHandler.factoryMethod = (menu, cell, evt) => {
        let selectCells = this.graphOjbect.getSelectionCells();
        if (selectCells.length == 0 && null != cell) {
          selectCells[selectCells.length] = cell;
        }
        //if(selectCells.length>0){
        menu.addItem("编辑", null, () => {
          if (selectCells.length > 0) {
            this.editNode(selectCells[0]);
          }
        });
        menu.addSeparator();
        menu.addItem("删除", null, () => {
          if (selectCells.length > 0) {
            this.deleteCells({ cells: selectCells, includeEdges: true });
          }
        });
        menu.addSeparator();
        menu.addItem("复制", null, () => {
          this.copy();
        });
        menu.addSeparator();
        menu.addItem("粘贴", null, () => {
          this.paste();
        });
        // }
      };
    },
    deleteCells({ cells = [], includeEdges = false, multilevel = true }) {
      if (!cells || !(cells instanceof Array)) {
        throw new Error("cells 必须是一个数组");
      }
      let tmpSet = new Set(cells);
      if (multilevel) {
        cells.forEach((cell) => {
          this.findDeleteCell(cell, tmpSet);
        });
      }
      this.graphOjbect.removeCells(Array.from(tmpSet), includeEdges);
      const xml = this.getModelXml();
      this.$emit("deleteCells", cells, xml);
    },
    findDeleteCell(cell, deleteSet) {
      const edges = cell.edges;
      // 删除-处理上下节点的报错
      if (edges) {
        for (let i = 0; i < edges.length; i++) {
          const item = edges[i];

          if (cell.id != item.source.id) {
            const { type, id } = item.source;
            // 设置上下节点 删除字段
            this.$store.commit("siddhi/setDel", { type, id });
            console.log(item.source, "上级");
          }
          if (cell.id != item.target.id) {
            const { type, id } = item.target;
            console.log(item.target, "下级");
            this.$store.commit("siddhi/setDel", { type, id });
          }
        }
      }

      deleteSet.add(cell);
      // 下边代码是删除当前节点下边所有的节点
      // if (cell.edges) {
      //   cell.edges.forEach((tmpEdge) => {
      //     if (tmpEdge.target !== cell) {
      //       deleteSet.add(tmpEdge.target);
      //       this.findDeleteCell(tmpEdge.target, deleteSet);
      //     }
      //   });
      // }
    },
    // 添加高亮/取消高亮
    sethighlight(edgeID, isDel) {
      var highlight = new mxCellHighlight(this.graphOjbect, "#FF4D4F", 2);
      const index = this.highlight.findIndex((item) => item.edgeID == edgeID);
      if (index == -1) {
        this.highlight.push({
          highlight,
          isDel,
          edgeID,
        });
      } else {
        this.$set(this.highlight[index], "isDel", isDel);
        this.$set(this.highlight[index], "edgeID", edgeID);
      }
      this.highlight.forEach((item) => {
        var cellSource = this.graphOjbect.getModel().getCell(item.edgeID);
        if (
          cellSource &&
          item.isDel &&
          item.edgeID &&
          !streamKey.includes(cellSource.type)
        ) {
          item.highlight.highlight(this.graphOjbect.view.getState(cellSource));
        } else {
          item.highlight.hide();
        }
      });
    },
    expandComponent() {
      let totalComponents = this.componentsData;
      totalComponents.map((comp) => {
        this.activeNames.push(comp.name);
      });
    },
    collapseComponent() {
      this.activeNames = [];
    },
    copy() {
      var cells = [];
      cells = this.graphOjbect.getSelectionCells();
      mxClipboard.copy(this.graphOjbect, cells);
    },
    paste() {
      mxClipboard.paste(this.graphOjbect);
    },
    initKeyHandler() {
      if (!this.graphOjbect) {
        throw new Error("graph 没有初始化");
      }
      // eslint-disable-next-line new-cap
      this.keyHandler = new mxKeyHandler(this.graphOjbect);

      this.keyHandler.bindControlKey(67, () => {
        this.copy();
      });
      // this.keyHandler.bindControlKey(88, () => {
      //   this.cut()
      // })
      this.keyHandler.bindControlKey(86, () => {
        this.paste();
      });
    },
    editNode(cell) {
      this.openDrawer(cell);
    },

    // packagecheck(value) {
    //   console.log(value);
    //   return new Promise((resolve, reject) => {
    //     Mealcheck(value).then((data) => {
    //       this.checkStatus = data.data;
    //       console.log(this.checkStatus);
    //       resolve(this.checkStatus)
    //     });
    //   });
    // },

    appConfig() {
      this.showRight = {};
      this.showRight.open = true;
      this.showRight.title = "设置";
      this.showRight.nodeType = "0";
      let xmlStr = this.getModelXml();
      this.showRight.mxJson = xmlStr;
      this.$emit("openRightDrawer", this.showRight);
    },
    showNode(cell, fontNode, AfterNode) {
      // console.info("前一个节点source：");
      // console.info(fontNode, cell, AfterNode);
      // console.info("后一个节点target:");
      // console.info(AfterNode);
      this.showRight = {};
      if (cell.vertex != undefined && cell.vertex == true) {
        //如果是节点query，需要验证
        let nodeJson = this.getNodeJson(cell); //根据当前图形节点id  将id对应的siddhi格式中的数据取出来
        this.showRight.id = cell.id;
        this.showRight.open = true;
        this.showRight.title = cell.title;
        this.showRight.nodeType = cell.type;
        this.showRight.objectState = this.objectState;
        let xmlStr = this.getModelXml();
        this.showRight.mxJson = xmlStr;
        this.showRight.relateCellData = {
          targetCell: AfterNode,
          sourceCell: fontNode,
        };
        Object.assign(this.showRight, { mxNode: nodeJson }); //要传递的json对象mxNode
        // Object.assign(this.showRight,{returnAppConfig:this.ObjectData.siddhiAppConfig})
        // console.info(" 调用父组件 ---打开右侧抽屉：");
        //console.info(JSON.stringify(nodeJson))
        this.$emit("openRightDrawer", this.showRight);
      }
    },
    read(graph, filename) {
      var req = mxUtils.load(filename);
      var root = req.getDocumentElement();
      var dec = new mxCodec(root.ownerDocument);
      dec.decode(root, graph.getModel());
    },
    importModelXML(xmlTxt, mxCellArray) {
      // var style = this.graphOjbect.getStylesheet().getDefaultEdgeStyle();
      // style[mxConstants.STYLE_SPACING] = 100;
      // style[mxConstants.STYLE_FONTSIZE] = 300;
      // this.graphOjbect.getStylesheet().putCellStyle("style1", style);
      // console.log(style, "====");
      if (xmlTxt != "") {
        var layout = new mxHierarchicalLayout(this.graphOjbect);
        this.graphOjbect.getModel().beginUpdate();
        try {
          const doc = mxUtils.parseXml(xmlTxt);
          const root = doc.documentElement;
          let dec = new mxCodec(root.ownerDocument);
          dec.decode(root, this.graphOjbect.getModel());

          layout.execute(this.graphOjbect.getDefaultParent());
        } finally {
          this.graphOjbect.getModel().endUpdate();
        }
      }
      ////////////////////组织状布局///不合适////////////////////
      // var layout = new mxFastOrganicLayout(this.graphOjbect,2);
      // this.graphOjbect.getModel().beginUpdate(0,2);
      // try {
      //   var doc = mxUtils.parseXml(xmlTxt,2);
      //   var dec = new mxCodec(doc,2);
      //   dec.decode(doc.documentElement, this.graphOjbect.getModel(),2);
      //
      //   var parent = this.graphOjbect.getDefaultParent(0,2);
      //
      //   layout.execute(parent,2);
      // }
      // finally {
      //   this.graphOjbect.getModel().endUpdate(0,2);
      // }
      ///////////////树状布局/////////
      // var layout = new mxCompactTreeLayout(this.graphOjbect);
      // this.graphOjbect.getModel().beginUpdate();
      // try {
      //   var doc = mxUtils.parseXml(xmlTxt);
      //   var dec = new mxCodec(doc);
      //   dec.decode(doc.documentElement, this.graphOjbect.getModel());
      //
      //   var parent = this.graphOjbect.getDefaultParent();
      //
      //   layout.execute(parent);
      // }
      // finally {
      //   this.graphOjbect.getModel().endUpdate();
      // }
      this._restoreModel();
    },
    _restoreModel() {
      Object.values(this.graphOjbect.getModel().cells).forEach((cell) => {
        if (cell.vertex && cell.data) {
          cell.data = JSON.parse(cell.data);
        }
      });
    },
    getNodeJson(node) {
      let tempNode;
      if (node.type != undefined) {
        let tempType = node.type;
        let length = tempType.split(".").length;
        let tempTypep1 = new Array();
        if ("" != tempType && length > 1) {
          tempTypep1 = tempType.split(".");
          if (this.activeTab.appData != undefined) {
            let typeList = this.activeTab.appData[tempTypep1[0]];
            let param1 = typeList[tempTypep1[1]];
            param1.forEach((param) => {
              if (param.id === node.id) {
                tempNode = param;
              }
            });
          }
        } else {
          if (this.activeTab.appData != undefined) {
            let streamList = this.activeTab.appData[node.type];
            if (streamList instanceof Array) {
              streamList.forEach((item) => {
                if (item.id === node.id) {
                  tempNode = item;
                }
              });
            } else {
              tempNode = streamList;
            }
          }
        }
      }
      return tempNode;
    },
    getModelXml() {
      var encoder = new mxCodec();
      var node = encoder.encode(this.graphOjbect.getModel());
      //mxUtils.popup(mxUtils.getPrettyXml(node), true);
      return mxUtils.getPrettyXml(node);
    },
  },
};

// <!--255白色192银灰色-->
</script>
<style lang="less" scoped>
.el-aside /deep/ .el-input__inner {
  width: 90%;
  border-top-width: 0px;
  border-left-width: 0px;
  border-right-width: 0px;
  border-bottom-width: 0px;
}
@import "@/assets/style/module/util.less";
.mLeft {
  height: 100%;
}
.mLeft .bl_move {
  height: 100%;
  cursor: col-resize;
  position: relative;
  z-index: 1;
  font-size: 12px;
  float: left;
}

.mLeft .bl_fold {
  font-size: 30px;
  position: absolute;
  top: 40%;
  left: -6px;
  cursor: pointer;
}
svg-icon:hover {
  cursor: pointer;
}

.mLeft .bl_fold i {
  position: relative;
}

.grid-content_main {
  font-family: Arial;

  .tool-bar {
    padding: 5px 15px 0px 0px;
    height: 20px;
    float: right;
    margin-right: 140px;
    border-radius: 4px;
  }

  .outline-wrapper {
    border: 1px solid #dedede;
    height: 150px;
    width: 150px;
    background: #fff;
    position: absolute;
    right: 10px;
    top: 0px;
    z-index: 1;
    > h4 {
      padding: 6px;
      font-size: 12px;
      border-bottom: 1px solid #e6e6e6;
    }
    #graphOutline {
      width: 90%;
      height: 90%;
      min-width: 150px;
      min-height: 150px;
    }
  }
}

.element-img {
  width: 20px;
  height: 20px;
  // margin-top: 10px;
  // margin-left: 31px;
  // alignment: center;
}
.element-title {
  text-align: center;
  height: 16px;
  font-size: 12px;
  font-family: Microsoft YaHei;
  font-weight: 400;
  line-height: 22px;
  color: #666666;
}
.element_ul {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  padding: 0 10px;
}
.divElement {
  // float: left;
  // margin-left: 10px;
  // margin-top: 1px;
  margin-bottom: 5px;
  width: 72px;
  height: 72px;
  background: rgba(233, 233, 233, 0.41);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

td {
  font-size: 6px;
  color: #299e61;
}

/deep/ .el-collapse-item__header {
  margin-left: 15px;
  color: rgba(153, 153, 153, 1);
  font-size: 12px;
  font-family: Microsoft YaHei;
  font-weight: 400;
  line-height: 22px;
}
/deep/ .el-collapse-item__content {
  padding-bottom: 0px;
}
.graphMain {
  position: relative;
  flex: 7;
  // padding: 10px;
}

/deep/ input::-webkit-input-placeholder {
  font-size: 6px;
}
/deep/ input::-ms-input-placeholder {
  font-size: 6px;
}
</style>
